ZW.TrackballControls = function (object, domElement, lookat) {

	var _this = this;
	var STATE = {
		NONE: -1,
		ROTATE: 0,
		ZOOM: 1,
		PAN: 2,
		TOUCH_ROTATE: 3,
		TOUCH_ZOOM_PAN: 4,
		TOUCH_PAN: 5
	};

	this.object = object;
	this.domElement = (domElement !== undefined) ? domElement : document;


	this.enabled = true;
	this.screen = {
		left: 0,
		top: 0,
		width: 0,
		height: 0
	};

	this.rotateSpeed = 1.0;
	this.zoomSpeed = 1.0;
	this.panSpeed = 1.0;

	this.noRotate = false;
	this.noZoom = false;
	this.noPan = false;

	this.staticMoving = true;
	this.dynamicDampingFactor = 0.2;

	this.keycount = 0;

	this.downKey = [];	//按键记录

	this.minDistance = 0;
	this.maxDistance = Infinity;

	this.keys = [65, 83, 68];

	this.target = new ZW.Vector3();

	this.mouse = new ZW.Vector2();	//滚轮缩放坐标

	var EPS = 0.000001;

	var lastPosition = new ZW.Vector3();

	var _state = STATE.NONE,
		_prevState = STATE.NONE,

		_eye = new ZW.Vector3(),

		_movePrev = new ZW.Vector2(),
		_moveCurr = new ZW.Vector2(),

		_lastAxis = new ZW.Vector3(),
		_lastAngle = 0,

		_zoomStart = new ZW.Vector2(),
		_zoomEnd = new ZW.Vector2(),

		_touchZoomDistanceStart = 0,
		_touchZoomDistanceEnd = 0,

		_panStart = new ZW.Vector2(),
		_panEnd = new ZW.Vector2();

	_myPan = new ZW.Vector3(),

		this.target0 = this.target.clone();
	this.position0 = this.object.position.clone();
	this.up0 = this.object.up.clone();

	var changeEvent = {
		type: 'change'
	};
	var startEvent = {
		type: 'start'
	};
	var endEvent = {
		type: 'end'
	};


	this.handleResize = function () {

		if (this.domElement === document) {

			this.screen.left = 0;
			this.screen.top = 0;
			this.screen.width = window.innerWidth;
			this.screen.height = window.innerHeight;

		} else {

			var box = this.domElement.getBoundingClientRect();
			var d = this.domElement.ownerDocument.documentElement;
			this.screen.left = box.left + window.pageXOffset - d.clientLeft;
			this.screen.top = box.top + window.pageYOffset - d.clientTop;
			this.screen.width = box.width;
			this.screen.height = box.height;

		}

	};

	this.handleEvent = function (event) {

		if (typeof this[event.type] == 'function') {

			this[event.type](event);

		}

	};

	var getMouseOnScreen = (function () {

		var vector = new ZW.Vector2();

		return function getMouseOnScreen(pageX, pageY) {

			vector.set(
				(pageX - _this.screen.left) / _this.screen.width,
				(pageY - _this.screen.top) / _this.screen.height
			);

			return vector;

		};

	}());

	var getMouseOnCircle = (function () {

		var vector = new ZW.Vector2();

		return function getMouseOnCircle(pageX, pageY) {

			vector.set(
				((pageX - _this.screen.width * 0.5 - _this.screen.left) / (_this.screen.width * 0.5)),
				((_this.screen.height + 2 * (_this.screen.top - pageY)) / _this.screen.width)
			);

			return vector;

		};

	}());

	this.rotateCamera = (function () {

		var axis = new ZW.Vector3(),
			quaternion = new ZW.Quaternion(),
			eyeDirection = new ZW.Vector3(),
			objectUpDirection = new ZW.Vector3(),
			objectSidewaysDirection = new ZW.Vector3(),
			moveDirection = new ZW.Vector3(),
			angle;

		return function rotateCamera() {
			moveDirection.set(_moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0);
			angle = moveDirection.length();
			_movePrev.copy(_moveCurr);
		};

	}());


	this.zoomCamera = function () {

			var factor;

			if (_state === STATE.TOUCH_ZOOM_PAN) {

			} else {
				if (isNaN(_this.zoomSpeed)) return;
				factor = (_zoomEnd.y - _zoomStart.y) * _this.zoomSpeed * 1;
				if (factor < 0.01 && factor > -0.01) return;

				//console.log(factor);
				var pos1 = GetWorldPosByMousePos([_this.mouse.x,_this.mouse.y]);

				ZW_activeCamera.zoom /= (1+factor);
				// if(ZW_activeCamera.zoom < 0.05) ZW_activeCamera.zoom = 0.05;
				// if(ZW_activeCamera.zoom > 5) ZW_activeCamera.zoom = 5;

				ZW_activeCamera.updateProjectionMatrix();

				
					var pos2 = GetWorldPosByMousePos([_this.mouse.x,_this.mouse.y]);

					ZW_activeCamera.position.x -= pos2[0] - pos1[0];
					ZW_activeCamera.position.y -= pos2[1] - pos1[1];

					ZW_activeCamera.updateProjectionMatrix();


				ShowProcess();

				_zoomStart.copy(_zoomEnd);
			}
	};

	this.panCamera = (function () {

		var mouseChange = new ZW.Vector2(),
			pan = new ZW.Vector3();

		return function panCamera() {

				mouseChange.copy(_panEnd).sub(_panStart);

				if (mouseChange.lengthSq() > 0.0001) {
					// console.log(_panStart);
					// console.log(_panEnd);

					var pos1 = GetWorldPosByMousePos([_panStart.x,_panStart.y]);
					var pos2 = GetWorldPosByMousePos([_panEnd.x,_panEnd.y]);

					ZW_activeCamera.position.x -= pos2[0] - pos1[0];
					ZW_activeCamera.position.y -= pos2[1] - pos1[1];
					// ZW_activeCamera.position.y += mouseChange.y * 2000;
					// ZW_activeCamera.position.x -= mouseChange.x* 2000;

					if (_this.staticMoving) {
						_panStart.copy(_panEnd);
					} else {
						//_panStart.add(mouseChange.subVectors(_panEnd, _panStart).multiplyScalar(_this.dynamicDampingFactor));
					}

					ShowProcess();

				}
		};

	}());

	this.checkDistances = function () {

		if (!_this.noZoom || !_this.noPan) {

			if (_eye.lengthSq() > _this.maxDistance * _this.maxDistance) {

				_this.object.position.addVectors(_this.target, _eye.setLength(_this.maxDistance));
				_zoomStart.copy(_zoomEnd);

			}

			if (_eye.lengthSq() < _this.minDistance * _this.minDistance) {

				_this.object.position.addVectors(_this.target, _eye.setLength(_this.minDistance));
				_zoomStart.copy(_zoomEnd);

			}

		}

	};

	this.update = function () {

		if (!_this.noZoom) {
			_this.zoomCamera();

		}

		if (!_this.noPan) {
			_this.panCamera();

		}

		if (!_this.noRotate) {
			_this.rotateCamera();
		}

	};

	this.reset = function () {

		_state = STATE.NONE;
		_prevState = STATE.NONE;

		_this.target.copy(_this.target0);
		_this.object.position.copy(_this.position0);
		_this.object.up.copy(_this.up0);

		_eye.subVectors(_this.object.position, _this.target);

		_this.object.lookAt(_this.target);

		_this.dispatchEvent(changeEvent);

		lastPosition.copy(_this.object.position);

	};


	function keydown(event) {

		_this.keycount++;
		var currKey = 0,
			e = e || event;
		currKey = e.keyCode || e.whisch || e.charCode;
		var keyName = String.fromCharCode(currKey);

		ZW_DropTime = new Date().getTime();
		_this.downKey.push(keyName);
	}

	function keyup(event) {

		var currKey = 0,
			e = e || event;
		currKey = e.keyCode || e.which || e.charCode;
		var keyName = String.fromCharCode(currKey);

		_this.downKey = [];

		_this.keycount = 0;
		
		ShowProcess();
	}

	function mousedown(event) {
		if(_this.noPan)
			return;

		if (_this.enabled === false) return;


		event.preventDefault();
		event.stopPropagation();

		if (_state === STATE.NONE) {
			_state = event.button;
		}

		if (_state === STATE.ROTATE && !_this.noRotate) {

			if (!ZW_MouseMode) {
				//_panStart.copy(getMouseOnScreen(event.pageX, event.pageY));
				_panStart.copy(new ZW.Vector2(event.pageX, event.pageY));
				_panEnd.copy(_panStart);
				// _moveCurr.copy(getMouseOnCircle(event.pageX, event.pageY));
				// _movePrev.copy(_moveCurr);
			}
		} else if (_state === STATE.ZOOM && !_this.noZoom) {

			if (ZW_MouseMode) {
				_panStart.copy(getMouseOnScreen(event.pageX, event.pageY));
				_panEnd.copy(_panStart);
			} else {
				_zoomStart.copy(getMouseOnScreen(event.pageX, event.pageY));
				_zoomEnd.copy(_zoomStart);
			}
		} else if (_state === STATE.PAN && !_this.noPan) {
			if (ZW_MouseMode) {
				_moveCurr.copy(getMouseOnCircle(event.pageX, event.pageY));
				_movePrev.copy(_moveCurr);
			} else {
				_panStart.copy(getMouseOnScreen(event.pageX, event.pageY));
				_panEnd.copy(_panStart);
			}


		}

		
		document.addEventListener('mouseup', mouseup, false);

		_this.dispatchEvent(startEvent);

	}

	function mousemove(event) {
		if(_this.noPan)
			return;

		if (_this.enabled === false) return;
	
		var worldPos = GetWorldPosByMousePos([event.pageX,event.pageY]);
		if(worldPos)
		OnMouseMove([worldPos[0],worldPos[1],event.pageX,event.pageY]);

		event.preventDefault();
		event.stopPropagation();

		if (_state === STATE.ROTATE && !_this.noRotate) {



			if (!ZW_MouseMode) {
				// _movePrev.copy(_moveCurr);
				// _moveCurr.copy(getMouseOnCircle(event.pageX, event.pageY));
				_panEnd.copy(new ZW.Vector2(event.pageX, event.pageY));
				//_panEnd.copy(getMouseOnScreen(event.pageX, event.pageY));
			}
		} else if (_state === STATE.ZOOM && !_this.noZoom) {

			if (ZW_MouseMode) {
				_panEnd.copy(getMouseOnScreen(event.pageX, event.pageY));
			} else {
				_zoomEnd.copy(getMouseOnScreen(event.pageX, event.pageY));
			}


		} else if (_state === STATE.PAN && !_this.noPan) {

			if (ZW_MouseMode) {
				_movePrev.copy(_moveCurr);
				_moveCurr.copy(getMouseOnCircle(event.pageX, event.pageY));
			} else {
				//_panEnd.copy(getMouseOnScreen(event.pageX, event.pageY));
			}

		}

	}

	function mouseup(event) {
		if(_this.noPan)
			return;

		if (_this.enabled === false) return;

		event.preventDefault();
		event.stopPropagation();

		_state = STATE.NONE;

		document.removeEventListener('mousemove', mousemove);
		document.removeEventListener('mouseup', mouseup);
		_this.dispatchEvent(endEvent);

	}

	function mousewheel(event) {
		if(_this.noZoom)
			return;

		if (_this.enabled === false) return;

		var worldPos = GetWorldPosByMousePos([event.pageX,event.pageY]);
		if(worldPos)
		OnMouseMove([worldPos[0],worldPos[1]]);

		_this.mouse.x = event.pageX;
		_this.mouse.y = event.pageY;

		// _this.mouse.x = ((event.pageX - ZW_renderer.domElement.getBoundingClientRect().left) / ZW_renderer.domElement.offsetWidth) * 2 - 1;
		// _this.mouse.y = -((event.pageY - ZW_renderer.domElement.getBoundingClientRect().top) / ZW_renderer.domElement.offsetHeight) * 2 + 1;

		event.preventDefault();
		event.stopPropagation();

		switch (event.deltaMode) {

			case 2:
				_zoomStart.y -= event.deltaY * 0.025;
				break;

			case 1:
				_zoomStart.y -= event.deltaY * 0.01;
				break;

			default:
				_zoomStart.y -= event.deltaY * 0.00025;
				break;

		}

		_this.dispatchEvent(startEvent);
		_this.dispatchEvent(endEvent);

	}

	function touchstart(event) {
		if (_this.enabled === false) return;

		switch (event.touches.length) {

			case 1:
				_state = STATE.TOUCH_ROTATE;
				_moveCurr.copy(getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
				_movePrev.copy(_moveCurr);
				break;
			case 2:
				_state = STATE.TOUCH_ZOOM_PAN;
				var dx = event.touches[0].pageX - event.touches[1].pageX;
				var dy = event.touches[0].pageY - event.touches[1].pageY;
				_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt(dx * dx + dy * dy);

				var x = (event.touches[0].pageX + event.touches[1].pageX) / 2;
				var y = (event.touches[0].pageY + event.touches[1].pageY) / 2;
				_panStart.copy(getMouseOnScreen(x, y));

				break;
			default:
				_state = STATE.TOUCH_PAN;
				var x = (event.touches[0].pageX + event.touches[1].pageX) / 2;
				var y = (event.touches[0].pageY + event.touches[1].pageY) / 2;
				_panStart.copy(getMouseOnScreen(x, y));
				_panEnd.copy(_panStart);
				break;

		}

		_this.dispatchEvent(startEvent);

	}

	function touchmove(event) {

		if (_this.enabled === false) return;

		event.preventDefault();
		event.stopPropagation();

		switch (event.touches.length) {

			case 1:
				_movePrev.copy(_moveCurr);
				_moveCurr.copy(getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
				break;

			default:
				var dx = event.touches[0].pageX - event.touches[1].pageX;
				var dy = event.touches[0].pageY - event.touches[1].pageY;
				_touchZoomDistanceEnd = parseInt(Math.sqrt(dx * dx + dy * dy));

				var x = (event.touches[0].pageX + event.touches[1].pageX) / 2;
				var y = (event.touches[0].pageY + event.touches[1].pageY) / 2;
				_panEnd.copy(getMouseOnScreen(x, y));

				if (ZW_bTouchMode) {
					_movePrev.copy(_moveCurr);
					_moveCurr.copy(getMouseOnCircle(event.touches[1].pageX, event.touches[1].pageY));
				}

				break;

		}

	}

	function touchend(event) {

		if (_this.enabled === false) return;

		switch (event.touches.length) {
			case 0:
				_state = STATE.NONE;
				break;
			default:
				_state = STATE.TOUCH_ROTATE;
				_moveCurr.copy(getMouseOnCircle(event.touches[0].pageX, event.touches[0].pageY));
				_movePrev.copy(_moveCurr);
				_panStart.copy(_panEnd);

				break;
		}

		_this.dispatchEvent(endEvent);

	}

	function contextmenu(event) {

		if (_this.enabled === false) return;

		event.preventDefault();

	}

	this.dispose = function () {

		this.domElement.removeEventListener('contextmenu', contextmenu, false);
		this.domElement.removeEventListener('mousedown', mousedown, false);
		this.domElement.removeEventListener('wheel', mousewheel, false);

		this.domElement.removeEventListener('touchstart', touchstart, false);
		this.domElement.removeEventListener('touchend', touchend, false);
		this.domElement.removeEventListener('touchmove', touchmove, false);

		document.removeEventListener('mousemove', mousemove, false);
		document.removeEventListener('mouseup', mouseup, false);

		window.removeEventListener('keydown', keydown, false);
		window.removeEventListener('keyup', keyup, false);

	};

	this.domElement.addEventListener('contextmenu', contextmenu, false);
	this.domElement.addEventListener('mousedown', mousedown, false);
	this.domElement.addEventListener('mousemove', mousemove, false);

	this.domElement.addEventListener('wheel', mousewheel, false);

	this.domElement.addEventListener('touchstart', touchstart, false);
	this.domElement.addEventListener('touchend', touchend, false);
	this.domElement.addEventListener('touchmove', touchmove, false);

	window.addEventListener('keydown', keydown, false);
	window.addEventListener('keyup', keyup, false);

	this.handleResize();

	this.update();

};

ZW.TrackballControls.prototype = Object.create(ZW.EventDispatcher.prototype);
ZW.TrackballControls.prototype.constructor = ZW.TrackballControls;
